package com.yth.bean;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * <p>SpringBoot启动流程</p>
 * <ol>
 *      <li>SmartInstantiationAwareBeanPostProcessor::predictBeanType                </li>
 *      <li>InstantiationAwareBeanPostProcessor::postProcessBeforeInstantiation      </li>
 *      <li>SmartInstantiationAwareBeanPostProcessor::determineCandidateConstructors </li>
 *      <li>InstantiationAwareBeanPostProcessor::postProcessAfterInstantiation       </li>
 *      <li>InstantiationAwareBeanPostProcessor::postProcessProperties               </li>
 *      <li>SmartInstantiationAwareBeanPostProcessor::getEarlyBeanReference          </li>
 *      <li>BeanNameAware::setBeanName                                               </li>
 *      <li>BeanFactoryAware::setBeanFactory                                         </li>
 *      <li>BeanPostProcessor::postProcessBeforeInitialization                       </li>
 *      <li>PostConstruct::postConstruct                                             </li>
 *      <li>InitializingBean::afterPropertiesSet                                     </li>
 *      <li>BeanPostProcessor::postProcessAfterInitialization                        </li>
 *      <li>PreDestroy::preDestroy                                                   </li>
 *      <li>DisposableBean::destroy                                                  </li>
 * </ol>
 *
 * @author yutianhong
 * @version 1.0
 * @since 2023/09/05 15:34
 */
@Slf4j
@Component
public class TestAwareBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {

    @Autowired
    TestCircleBean testCircleBean;

    @Override
    public void setBeanName(String name) {
        // 在bean的实例化之后，初始化之前
        // 当TestBeanNameAware这个bean进行初始化之前，这个方法将会被调用
        log.info("[BeanNameAware::setBeanName] \t>>> name: {}", name);
        assert name.equals("testBeanNameAware");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        // 在bean实例化之后，初始化之前
        // 可以在此对当前bean进行定制逻辑处理
        log.info("[BeanFactoryAware::setBeanFactory]");
    }

    @PostConstruct
    public void postConstruct() {
        // 初始化阶段中，具体在依赖注入完成之后
        log.info("[TestPostConstruct::init]");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // bean初始化过程中。当这个bean全部属性都被设置完成后，回调afterPropertiesSet方法
        log.info("[InitializingBean::afterPropertiesSet]");
    }

    @PreDestroy
    public void preDestroy() {
        // 当此对象销毁前
        log.info("[TestPreDestroy::preDestroy]");
    }

    @Override
    public void destroy() throws Exception {
        // 当此对象被销毁时回调此方法
        log.info("[DisposableBean::destroy]");
    }
}
